<template>
  <!-- 
    动态模块加载器组件
    功能：
    1. 动态加载和显示模块
    2. 处理加载状态和错误
    3. 提供重试和卸载功能
    4. 支持模块配置和事件处理
  -->
  <div class="dynamic-module-loader">
    <!-- 加载状态 -->
    <div v-if="loadState === 'loading'" class="loading-state">
      <div class="loading-content">
        <el-skeleton :rows="3" animated />
        <div class="loading-info">
          <el-icon class="loading-icon"><Loading /></el-icon>
          <span class="loading-text">正在加载模块 {{ moduleName }}...</span>
          <div v-if="loadProgress > 0" class="progress-bar">
            <el-progress 
              :percentage="loadProgress" 
              :stroke-width="2"
              :show-text="false"
              status="active"
            />
          </div>
        </div>
      </div>
    </div>

    <!-- 错误状态 -->
    <div v-else-if="loadState === 'error'" class="error-state">
      <el-result
        icon="error"
        :title="`模块 ${moduleName} 加载失败`"
        :sub-title="errorMessage"
      >
        <template #extra>
          <el-button-group>
            <el-button type="primary" @click="retryLoad" :loading="retrying">
              <el-icon><RefreshRight /></el-icon>
              重试
            </el-button>
            <el-button @click="unloadModule">
              <el-icon><Close /></el-icon>
              卸载
            </el-button>
          </el-button-group>
          <div v-if="errorDetails" class="error-details">
            <el-collapse>
              <el-collapse-item title="错误详情">
                <pre class="error-stack">{{ errorDetails }}</pre>
              </el-collapse-item>
            </el-collapse>
          </div>
        </template>
      </el-result>
    </div>

    <!-- 已加载状态 -->
    <div v-else-if="loadState === 'loaded' && moduleComponent" class="loaded-state">
      <div class="module-header">
        <div class="module-info">
          <el-icon 
            :size="20" 
            :color="getModuleColor(moduleInfo?.category)"
            class="module-icon"
          >
            <component :is="getModuleIcon(moduleInfo?.category)" />
          </el-icon>
          <span class="module-name">{{ moduleName }}</span>
          <el-tag size="small" :type="getModuleTagType(moduleInfo?.category)">
            {{ moduleInfo?.category }}
          </el-tag>
        </div>
        <div class="module-actions">
          <el-button 
            size="small" 
            type="primary"
            @click="showConfigDialog = true"
            :title="'配置模块'"
          >
            <el-icon><Setting /></el-icon>
          </el-button>
          <el-button 
            size="small" 
            @click="refreshModule"
            :title="'刷新模块'"
            :loading="refreshing"
          >
            <el-icon><Refresh /></el-icon>
          </el-button>
          <el-button 
            size="small" 
            @click="unloadModule"
            :title="'卸载模块'"
          >
            <el-icon><Close /></el-icon>
          </el-button>
        </div>
      </div>
      
      <div class="module-content">
        <component
          :is="moduleComponent"
          v-bind="moduleProps"
          @module-event="handleModuleEvent"
          @module:mounted="handleModuleMounted"
          @module:unmounted="handleModuleUnmounted"
          @module:config-updated="handleModuleConfigUpdated"
          @module:refreshed="handleModuleRefreshed"
          @module:error="handleModuleError"
        />
      </div>
    </div>

    <!-- 未加载状态 -->
    <div v-else class="unloaded-state">
      <div class="unload-content">
        <el-empty :description="`模块 ${moduleName} 未加载`">
          <el-button type="primary" @click="loadModule">
            <el-icon><Plus /></el-icon>
            加载模块
          </el-button>
        </el-empty>
      </div>
    </div>

    <!-- 模块配置对话框 -->
    <el-dialog
      v-model="showConfigDialog"
      :title="`配置 ${moduleName}`"
      width="600px"
    >
      <div class="config-content">
        <el-form
          ref="configFormRef"
          :model="configForm"
          :rules="configRules"
          label-width="120px"
        >
          <el-form-item label="模块配置" prop="config">
            <el-input
              v-model="configForm.config"
              type="textarea"
              :rows="8"
              placeholder="请输入JSON格式的模块配置"
            />
          </el-form-item>
          
          <el-form-item label="自动加载" prop="autoLoad">
            <el-switch v-model="configForm.autoLoad" />
          </el-form-item>
          
          <el-form-item label="启用缓存" prop="enableCache">
            <el-switch v-model="configForm.enableCache" />
          </el-form-item>
        </el-form>
      </div>
      
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="showConfigDialog = false">取消</el-button>
          <el-button type="primary" @click="saveConfig" :loading="savingConfig">
            保存配置
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
/**
 * 动态模块加载器组件
 * 
 * 功能：
 * 1. 动态加载和显示模块
 * 2. 处理加载状态和错误
 * 3. 提供重试和卸载功能
 * 4. 支持模块配置和事件处理
 * 5. 集成到现有组件系统
 */

import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { 
  Loading, 
  Refresh, 
  Close, 
  Plus, 
  Setting, 
  RefreshRight,
  Grid,
  Monitor,
  Message,
  Document,
  VideoPlay
} from '@element-plus/icons-vue'
import { useModuleManager } from '../composables/useModuleManager'
import type { DynamicModule, ModuleConfig } from '../dynamic/types'

interface Props {
  /** 模块ID */
  moduleId: string
  /** 是否自动加载 */
  autoLoad?: boolean
  /** 模块属性 */
  moduleProps?: Record<string, any>
  /** 加载超时时间 */
  timeout?: number
  /** 最大重试次数 */
  maxRetries?: number
}

interface Emits {
  /** 模块加载完成事件 */
  loaded: [moduleId: string, component: any]
  /** 模块加载错误事件 */
  error: [moduleId: string, error: Error]
  /** 模块卸载事件 */
  unloaded: [moduleId: string]
  /** 模块事件 */
  'module-event': [moduleId: string, event: string, payload: any]
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

// ==================== 依赖注入 ====================
const moduleManager = useModuleManager()

// ==================== 响应式状态 ====================
/** 加载状态 */
const loadState = ref<'unloaded' | 'loading' | 'loaded' | 'error'>('unloaded')
/** 模块组件 */
const moduleComponent = ref<any>(null)
/** 错误消息 */
const errorMessage = ref<string>('')
/** 错误详情 */
const errorDetails = ref<string>('')
/** 重试状态 */
const retrying = ref(false)
/** 刷新状态 */
const refreshing = ref(false)
/** 加载进度 */
const loadProgress = ref(0)

/** 对话框状态 */
const showConfigDialog = ref(false)
const savingConfig = ref(false)

/** 配置表单 */
const configFormRef = ref<FormInstance>()
const configForm = ref({
  config: '{}',
  autoLoad: true,
  enableCache: true
})

/** 配置表单验证规则 */
const configRules: FormRules = {
  config: [
    { required: true, message: '请输入模块配置', trigger: 'blur' },
    {
      validator: (rule, value, callback) => {
        try {
          JSON.parse(value)
          callback()
        } catch (error) {
          callback(new Error('请输入有效的JSON格式'))
        }
      },
      trigger: 'blur'
    }
  ]
}

// ==================== 计算属性 ====================
/** 模块名称 */
const moduleName = computed(() => {
  const module = moduleManager.getModule(props.moduleId)
  return module?.name || props.moduleId
})

/** 模块信息 */
const moduleInfo = computed(() => {
  return moduleManager.getModule(props.moduleId)
})

// ==================== 生命周期钩子 ====================
/**
 * 组件挂载时初始化
 */
onMounted(() => {
  initializeModule()
  setupEventListeners()
})

/**
 * 组件卸载时清理
 */
onUnmounted(() => {
  cleanupEventListeners()
  if (loadState.value === 'loaded') {
    unloadModule()
  }
})

// ==================== 模块初始化 ====================
/**
 * 初始化模块
 */
async function initializeModule() {
  try {
    // 注册模块（如果需要）
    await registerModuleIfNeeded()
    
    // 自动加载
    if (props.autoLoad) {
      await loadModule()
    }
  } catch (error) {
    console.error('Failed to initialize module:', error)
  }
}

/**
 * 如果需要，注册模块
 */
async function registerModuleIfNeeded() {
  const existingModule = moduleManager.getModule(props.moduleId)
  if (existingModule) {
    return
  }

  // 从后端获取模块信息并注册
  try {
    const response = await fetch(`/api/widgets/${props.moduleId}`)
    const widgetData = await response.json()
    
    const module: DynamicModule = {
      id: props.moduleId,
      name: widgetData.name,
      version: widgetData.version,
      description: widgetData.description,
      category: widgetData.category,
      author: widgetData.author_name || 'System',
      entry: 'index.vue',
      permissions: [],
      config_schema: widgetData.config_schema,
      frontend_files: widgetData.frontend_files,
      is_active: widgetData.is_active,
      created_at: widgetData.created_at,
      updated_at: widgetData.updated_at
    }

    await moduleManager.registerModule(module, {
      autoLoadDependencies: false,
      preload: false
    })
  } catch (error) {
    console.error('Failed to register module:', error)
    throw error
  }
}

// ==================== 模块加载功能 ====================
/**
 * 加载模块
 */
async function loadModule() {
  if (loadState.value === 'loading') return
  
  loadState.value = 'loading'
  errorMessage.value = ''
  errorDetails.value = ''
  loadProgress.value = 0
  
  // 模拟加载进度
  const progressInterval = setInterval(() => {
    if (loadProgress.value < 90) {
      loadProgress.value += Math.random() * 20
    }
  }, 200)

  try {
    const component = await moduleManager.loadModule(props.moduleId, {
      timeout: props.timeout || 30000,
      maxRetries: props.maxRetries || 3
    })
    
    moduleComponent.value = component
    loadState.value = 'loaded'
    loadProgress.value = 100
    
    emit('loaded', props.moduleId, component)
    
    ElMessage.success(`模块 ${moduleName.value} 加载成功`)
  } catch (error) {
    loadState.value = 'error'
    errorMessage.value = error instanceof Error ? error.message : 'Unknown error'
    errorDetails.value = error instanceof Error ? error.stack || '' : ''
    
    emit('error', props.moduleId, error as Error)
    
    ElMessage.error(`模块 ${moduleName.value} 加载失败: ${errorMessage.value}`)
  } finally {
    clearInterval(progressInterval)
  }
}

/**
 * 重试加载
 */
async function retryLoad() {
  if (retrying.value) return
  
  retrying.value = true
  try {
    await loadModule()
  } finally {
    retrying.value = false
  }
}

/**
 * 卸载模块
 */
async function unloadModule() {
  try {
    await moduleManager.unloadModule(props.moduleId)
    moduleComponent.value = null
    loadState.value = 'unloaded'
    loadProgress.value = 0
    
    emit('unloaded', props.moduleId)
    
    ElMessage.success(`模块 ${moduleName.value} 已卸载`)
  } catch (error) {
    console.error('Failed to unload module:', error)
    ElMessage.error(`卸载模块失败: ${error instanceof Error ? error.message : 'Unknown error'}`)
  }
}

/**
 * 刷新模块
 */
async function refreshModule() {
  if (refreshing.value) return
  
  refreshing.value = true
  try {
    await moduleManager.reloadModule(props.moduleId)
    ElMessage.success(`模块 ${moduleName.value} 刷新成功`)
  } catch (error) {
    console.error('Failed to refresh module:', error)
    ElMessage.error(`刷新模块失败: ${error instanceof Error ? error.message : 'Unknown error'}`)
  } finally {
    refreshing.value = false
  }
}

// ==================== 配置管理 ====================
/**
 * 保存配置
 */
async function saveConfig() {
  if (!configFormRef.value) return
  
  try {
    await configFormRef.value.validate()
    savingConfig.value = true
    
    // 解析配置
    const config = JSON.parse(configForm.value.config)
    
    // 更新模块属性
    Object.assign(props.moduleProps || {}, config)
    
    showConfigDialog.value = false
    ElMessage.success('模块配置已保存')
  } catch (error) {
    ElMessage.error('保存配置失败: ' + (error instanceof Error ? error.message : 'Unknown error'))
  } finally {
    savingConfig.value = false
  }
}

// ==================== 事件处理 ====================
/**
 * 处理模块事件
 */
function handleModuleEvent(event: string, payload: any) {
  emit('module-event', props.moduleId, event, payload)
}

/**
 * 处理模块挂载事件
 */
function handleModuleMounted(config: ModuleConfig) {
  console.log(`Module ${props.moduleId} mounted with config:`, config)
}

/**
 * 处理模块卸载事件
 */
function handleModuleUnmounted() {
  console.log(`Module ${props.moduleId} unmounted`)
}

/**
 * 处理模块配置更新事件
 */
function handleModuleConfigUpdated(config: ModuleConfig) {
  console.log(`Module ${props.moduleId} config updated:`, config)
  configForm.value.config = JSON.stringify(config, null, 2)
}

/**
 * 处理模块刷新事件
 */
function handleModuleRefreshed() {
  console.log(`Module ${props.moduleId} refreshed`)
}

/**
 * 处理模块错误事件
 */
function handleModuleError(error: Error) {
  console.error(`Module ${props.moduleId} error:`, error)
  ElMessage.error(`模块错误: ${error.message}`)
}

// ==================== 事件监听器设置 ====================
/**
 * 设置事件监听器
 */
function setupEventListeners() {
  moduleManager.on('module:loaded', handleModuleLoaded)
  moduleManager.on('module:error', handleModuleManagerError)
  moduleManager.on('module:unloaded', handleModuleUnloaded)
}

/**
 * 清理事件监听器
 */
function cleanupEventListeners() {
  moduleManager.off('module:loaded', handleModuleLoaded)
  moduleManager.off('module:error', handleModuleManagerError)
  moduleManager.off('module:unloaded', handleModuleUnloaded)
}

/**
 * 处理模块管理器加载事件
 */
function handleModuleLoaded(moduleId: string) {
  if (moduleId === props.moduleId) {
    const state = moduleManager.getModuleState(moduleId)
    if (state?.status === 'loaded') {
      moduleComponent.value = state.component
      loadState.value = 'loaded'
    }
  }
}

/**
 * 处理模块管理器错误事件
 */
function handleModuleManagerError(moduleId: string, error: Error) {
  if (moduleId === props.moduleId) {
    loadState.value = 'error'
    errorMessage.value = error.message
    errorDetails.value = error.stack || ''
  }
}

/**
 * 处理模块管理器卸载事件
 */
function handleModuleUnloaded(moduleId: string) {
  if (moduleId === props.moduleId) {
    moduleComponent.value = null
    loadState.value = 'unloaded'
  }
}

// ==================== UI 辅助函数 ====================
/**
 * 根据模块分类获取对应的图标
 */
function getModuleIcon(category?: string): string {
  const iconMap: Record<string, any> = {
    'default': Grid,
    'system': Setting,
    'tool': Setting,
    'dashboard': Monitor,
    'communication': Message,
    'file': Document,
    'entertainment': VideoPlay
  }
  return iconMap[category || 'default'] || Grid
}

/**
 * 根据模块分类获取对应的颜色
 */
function getModuleColor(category?: string): string {
  const colorMap: Record<string, string> = {
    'default': '#409EFF',
    'system': '#909399',
    'tool': '#E6A23C',
    'dashboard': '#67C23A',
    'communication': '#8B5CF6',
    'file': '#F56C6C',
    'entertainment': '#FF6B6B'
  }
  return colorMap[category || 'default'] || '#409EFF'
}

/**
 * 根据模块分类获取对应的标签类型
 */
function getModuleTagType(category?: string): string {
  const typeMap: Record<string, string> = {
    'default': 'primary',
    'system': 'info',
    'tool': 'warning',
    'dashboard': 'success',
    'communication': 'danger',
    'file': 'danger',
    'entertainment': 'danger'
  }
  return typeMap[category || 'default'] || 'primary'
}

// ==================== 监听器 ====================
/**
 * 监听模块属性变化
 */
watch(() => props.moduleProps, (newProps) => {
  if (newProps && loadState.value === 'loaded') {
    configForm.value.config = JSON.stringify(newProps, null, 2)
  }
}, { deep: true, immediate: true })
</script>

<style scoped>
.dynamic-module-loader {
  width: 100%;
  height: 100%;
  min-height: 200px;
}

/* 加载状态 */
.loading-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  background: var(--bg-color-secondary);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
}

.loading-content {
  width: 100%;
  max-width: 400px;
}

.loading-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin-top: 20px;
}

.loading-icon {
  font-size: 24px;
  color: var(--primary-color);
  animation: spin 1s linear infinite;
}

.loading-text {
  font-size: 14px;
  color: var(--text-color-secondary);
  text-align: center;
}

.progress-bar {
  width: 100%;
  margin-top: 8px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 错误状态 */
.error-state {
  padding: 20px;
  background: var(--bg-color-secondary);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
}

.error-details {
  margin-top: 20px;
}

.error-stack {
  background: var(--bg-color);
  padding: 12px;
  border-radius: var(--radius-md);
  font-size: 12px;
  color: var(--error-color);
  white-space: pre-wrap;
  word-break: break-all;
  max-height: 200px;
  overflow-y: auto;
}

/* 已加载状态 */
.loaded-state {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--card-bg);
  overflow: hidden;
}

.module-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  background: var(--bg-color-secondary);
  border-bottom: 1px solid var(--border-color);
}

.module-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.module-icon {
  flex-shrink: 0;
}

.module-name {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-color);
}

.module-actions {
  display: flex;
  gap: 8px;
}

.module-content {
  padding: 20px;
}

/* 未加载状态 */
.unloaded-state {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  background: var(--bg-color-secondary);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
}

.unload-content {
  text-align: center;
}

/* 配置对话框 */
.config-content {
  padding: 20px 0;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .dynamic-module-loader {
    min-height: 150px;
  }
  
  .loading-state,
  .error-state,
  .unloaded-state {
    padding: 20px 16px;
  }
  
  .module-header {
    flex-direction: column;
    gap: 12px;
    align-items: flex-start;
  }
  
  .module-actions {
    align-self: stretch;
  }
  
  .module-actions .el-button {
    flex: 1;
  }
  
  .module-content {
    padding: 16px;
  }
}

/* 暗色主题适配 */
@media (prefers-color-scheme: dark) {
  .loading-state,
  .error-state,
  .unloaded-state {
    background: var(--bg-color);
    border-color: var(--border-color);
  }
  
  .module-header {
    background: var(--bg-color);
    border-color: var(--border-color);
  }
}
</style>
